/*
	xmlParser.cc
	--------------------
	
	Author: Olivier Sputael
	
	This file is the definition of class functions that will parse a xml file.
*/

#include <dsl_codi/xmlParser.h>

/*
		PUBLIC METHODS
		--------------
*/

/**
  * @param filename the xml file to parse
  *
  * Initializes the parsing
  */
XmlParser::XmlParser (const char* filename) {
	LIBXML_TEST_VERSION
	reader = xmlReaderForFile(filename, NULL, 0);
	
	cout << "*** Parsing file: " << filename << " ***" << endl;
	
	if (reader == NULL) {
		cerr << "Unable to open " << filename << endl;
		abort();
	}
}

XmlParser::~XmlParser () {}

/**
  * Terminates the parsing, by freeing the reader
  */
void XmlParser::endParsing () {
	xmlFreeTextReader(reader);
}


/**
  * @return true if reading was successful, false otherwise
  *
  * Read the next information
  */
bool XmlParser::xml_read_tag (char* tag) {
	return read_next(tag);
}

/**
  * @return the string containing the name of the tag we just read
  *
  * Get the name of the last read tag
  */
char* XmlParser::get_read_tag () {
	return (char*)xmlTextReaderConstName(reader);
}

/**
  * @return true if the last read tag is empty, false otherwise
  *
  * Determine if tag contains informations
  */
bool XmlParser::is_empty_elt () {
	return xmlTextReaderIsEmptyElement(reader);
}

/**
  * @return the integer describing the node type
  *
  * Gets the node type of the last read tag (opening, closing, ...)
  */
int XmlParser::get_node_type () {
	return xmlTextReaderNodeType(reader);
}

/** 
  * @return a boolean value telling whether an ending tag has been read 
  * 
  * </method>, </statements> & </instruction> are not read in their respective functions due to complex
  * structure of these blocks. So, we have to read one of these tag before we can read <header> block
  */
bool XmlParser::end_tag_read () {
	if (read_next("method"))
		return true;
	else if (strcmp((char*)xmlTextReaderConstName(reader), "statements") == 0)
		return true;
	else if (strcmp((char*)xmlTextReaderConstName(reader), "instruction") == 0)
		return true;
	else 
		return false;
}

/** 
  * @return a boolean value that determines whether a header tag has been read
  *
  * Check whether a header tag has been read
  */
bool XmlParser::header_tag_read () {
	if (strcmp(get_read_tag(), "header_channel") == 0)
		return true;
	else if (strcmp(get_read_tag(), "header_program") == 0)
		return true;
	else if (strcmp(get_read_tag(), "header_type") == 0) 
		return true;
	else if (strcmp(get_read_tag(), "header_variable") == 0)
		return true;
	else if (strcmp(get_read_tag(), "header_method") == 0) 
		return true;
	else if (strcmp(get_read_tag(), "header_start_node") == 0)
		return true;
	else if (strcmp(get_read_tag(), "header_instruction") == 0)
		return true;
	else if (strcmp(get_read_tag(), "header_trigger") == 0)
		return true;
	else if (strcmp(get_read_tag(), "header_operation") == 0)
		return true;
	else if (strcmp(get_read_tag(), "header_sequence") == 0)
		return true;
	else if (strcmp(get_read_tag(), "header_statements") == 0)
		return true;
	else 
		return false;
}

/**
  * @param _hdr the header struct to modify
  *
  * Reads the <header> block 
  */
void XmlParser::parse_xml_header (PARSED_HEADER_STRUCT& _hdr) {
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_header: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	if (end_tag_read()) {
		// As we read an ending tag, we have to read the carriage return and the tag header 
		if (!read_next("#text")) {
			cerr << "parse_xml_header: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// At the end of the xml file, we have </statement> followed by </program>.
		// So, if we are in this case, we do not have to read <header> !
		if (!read_next("program")) {
			// reading null value which corresponds to carriage return
			if (!header_tag_read()) {
				cerr << "parse_xml_header: Parse error, expected <header>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
		}
	}
	// As the main read_loop in cfg_file_reader.cc reads <header> blocks, we could get here and read </program>
	if (strcmp((char*)xmlTextReaderConstName(reader), "program") == 0) {
		_hdr.opcode = -1; // end of parsing
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_header: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading </dSL_program>
		if (!read_next("dSL_program")) {
			cerr << "parse_xml_header: Parse error, expected </dSL_program>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	else {
		// reading <header>
		// if (strcmp((char*)xmlTextReaderConstName(reader), "header") != 0) {
		if (!header_tag_read()) {
			cerr << "parse_xml_header: Parse error, expected <header>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_header: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <opcode>
		if (!read_next("opcode")) {
			cerr << "parse_xml_header: Parse error, expected <opcode>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_hdr.opcode = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"));
		// reading text value
		if (!read_next("#text")) {
			// text is empty, we should have read </opcode>
			if (strcmp((char*)xmlTextReaderConstName(reader), "opcode") != 0) {
				cerr << "parse_xml_header: Parse error, expected </opcode>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
			sprintf(_hdr.opcode_txt, "");
		}
		else {
			sprintf(_hdr.opcode_txt, "%s", xmlTextReaderConstValue(reader));
			// reading </opcode>
			if (!read_next("opcode")) {
				cerr << "parse_xml_header: Parse error, expected </opcode>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_header: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <comment>
		if (!read_next("comment")) {
			cerr << "parse_xml_header: Parse error, expected <comment>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading text value
		if (!read_next("#text")) {
			// if the text is empty, we should have read the closing tag </comment>
			if (strcmp((char*)xmlTextReaderConstName(reader), "comment") != 0) {
				cerr << "parse_xml_header: Parse error, expected </comment>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
			// we read the closing tag which means the text is empty
			sprintf(_hdr.comment, "");
		}
		else {
			// we read the text value
			char* tmp = (char*)xmlTextReaderConstValue(reader);
			memmove(_hdr.comment, tmp, MAX_DSL_COMMENT_SIZE+1);
			// then, we read </comment>
			if (!read_next("comment")) {
				cerr << "parse_xml_header: Parse error, expected </comment>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_header: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <line_numer>
		if (!read_next("line_number")) {
			cerr << "parse_xml_header: Parse error, expected <line_number>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_hdr.start_line_1 = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"start_1"));
		_hdr.end_line_1 = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"end_1"));
		_hdr.start_line_2 = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"start_2"));
		_hdr.end_line_2 = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"end_2"));
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_header: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <position>
		if (!read_next("position")) {
			cerr << "parse_xml_header: Parse error, expected <position>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_hdr.begin_pos_1 = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"begin_1"));
		_hdr.end_pos_1 = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"end_1"));
		_hdr.begin_pos_2 = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"begin_2"));
		_hdr.end_pos_2 = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"end_2"));
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_header: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading </header>
		xmlTextReaderRead(reader);
		// if (!read_next("header")) {
		if (!header_tag_read()) {
			cerr << "parse_xml_header: Parse error, expected </header>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_header: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
}

/**
  * @param prog_name a string that will contain the program name
  *
  * Reads the <program> block
  */
void XmlParser::parse_xml_program (char _prg[SL_MAX_IDENTIFIER_LEN]) {
	// reading <program>
	if (!read_next("program")) {
		cerr << "parse_xml_program: Parse error, expected <program>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	sprintf(_prg, "%s", xmlTextReaderGetAttribute(reader, (xmlChar*)"name"));
	// parse_xml_header(_prg.header);
	
	/*
	// reading <types>
	if (!read_next("types")) {
		cerr << "parse_xml_program: Parse error, expected <types>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	if (!xmlTextReaderIsEmptyElement(reader)) {
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_program: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading every <type> block we have
		while (read_next("type")) {
			_prg.types.push_back(parse_xml_types());
		}
		// We finished to read <type> blocks, we should have read </types>
		if (strcmp((char*)xmlTextReaderConstName(reader), "types") != 0) {
			cerr << "parse_xml_program: Parse error, expected </types>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_program: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <variables>
	if (!read_next("variables")) {
		cerr << "parse_xml_program: Parse error, expected <variables>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	if (!xmlTextReaderIsEmptyElement(reader)) {
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_program: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading every <variable> block we have
		while (read_next("variable")) {
			_prg.vars.push_back(parse_xml_vars());
		}
		// We finished to read <variable> blocks, we should have read </variables>
		if (strcmp((char*)xmlTextReaderConstName(reader), "variables") != 0) {
			cerr << "parse_xml_program: Parse error, expected </variables>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_program: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <methods_and_whens>
	if (!read_next("methods_and_whens")) {
		cerr << "parse_xml_program: Parse error, expected <methods_and_whens>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	if (!xmlTextReaderIsEmptyElement(reader)) {
		_prg.meth_whens = parse_xml_methods_whens();
	}
	else {
		// reading #text
		if (!read_next("#text")) {
			cerr << "parse_xml_program: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// Loop to read one or more <statements> blocks
	while (read_next("statements")) {
		_prg.statements.push_back(parse_xml_stmts());
	}
	// finished reading <statements> blocks, we should have read </program>
	if (strcmp((char*)xmlTextReaderConstName(reader), "program") != 0) {
		cerr << "parse_xml_program: Parse error, expected </program>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_program: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}*/
}

/**
  * @param _chn the struct that will contain channel info
  *
  * This function is called when we detect the tag <protocol>. We then parse the 
  * content of the <protocol> block and we return the struct containing these
  * information.
  */
void XmlParser::parse_xml_channel (PARSED_CHANNEL_STRUCT& _chn) {
	// reading <channel>
	if (!read_next("channel")) {
		cerr << "parse_xml_channel: Parse error, expected <channel>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// getting attributes
	_chn.chan_id = strtoul((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"), NULL, 0);
	sprintf(_chn.name, "%s", xmlTextReaderGetAttribute(reader, (xmlChar*)"name"));
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_channel: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <protocol_name>
	if (!read_next("protocol_name")) {
		cerr << "parse_xml_channel: Parse error, expected <protocol_name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </protocol_name>
		if (strcmp((char*)xmlTextReaderConstName(reader), "protocol_name") != 0) {
			cerr << "parse_xml_channel: Parse error, expected </protocol_name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		sprintf(_chn.prot_name, "");
	}
	else {
		char* tmp = (char*)xmlTextReaderConstValue(reader);
		memmove(_chn.prot_name, tmp, SL_MAX_IDENTIFIER_LEN);
		// reading </protocol_name>
		if (!read_next("protocol_name")) {
			cerr << "parse_xml_channel: Parse error, expected </protocol_name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_channel: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <physical_channel>
	if (!read_next("physical_channel")) {
		cerr << "parse_xml_channel: Parse error, expected <physical_channel>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading the text value
	if (!read_next("#text")) {
		// If the text is empty, we should have read the closing tag </physical_channel>
		if (strcmp((char*)xmlTextReaderConstName(reader), "physical_channel") != 0) {
			cerr << "parse_xml_channel: Parse error, expected </physical_channel>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// we read the closing tag which means the text is empty
		sprintf(_chn.phys_chan, "");
	}
	else { 
		char* tmp = (char*)xmlTextReaderConstValue(reader);
		memmove(_chn.phys_chan, tmp, SL_MAX_IDENTIFIER_LEN);
		// and then </physical_channel>
		if (!read_next("physical_channel")) {
			cerr << "parse_xml_channel: Parse error, expected </physical_channel>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_channel: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <parameters>
	if (!read_next("parameters")) {
		cerr << "parse_xml_channel: Parse error, expected <parameters>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading the text value
	if (!read_next("#text")) {
		// If the text is empty, we should have read the closing tag </parameters>
		if (strcmp((char*)xmlTextReaderConstName(reader), "parameters") != 0) {
			cerr << "parse_xml_channel: Parse error, expected </parameters>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// we read the closing tag which means the text is empty
		sprintf(_chn.params, "");
	}
	else {
		// Ok, we can read the text value
		char* tmp = (char*)xmlTextReaderConstValue(reader);
		memmove(_chn.params, tmp, SL_MAX_IDENTIFIER_LEN);
		// and then </parameters>
		if (!read_next("parameters")) {
			cerr << "parse_xml_channel: Parse error, expected </parameters>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_channel: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <speed>
	if (!read_next("speed")) {
		cerr << "parse_xml_channel: Parse error, expected <speed>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </speed>
		if (strcmp((char*)xmlTextReaderConstName(reader), "speed") != 0) {
			cerr << "parse_xml_channel: Parse error, expected </speed>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_chn.speed = 0;
	}
	else {
		_chn.speed = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </speed>
		if (!read_next("speed")) {
			cerr << "parse_xml_channel: Parse error, expected </speed>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_channel: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <dsl_color>
	if (!read_next("dsl_color")) {
		cerr << "parse_xml_channel: Parse error, expected <dsl_color>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty we should have read </dsl_color>
		if (strcmp((char*)xmlTextReaderConstName(reader), "dsl_color") != 0) {
			cerr << "parse_xml_channel: Parse error, expected </dsl_color>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		else
			_chn.color = 0;
	}
	else {
		_chn.color = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </dsl_color>
		if (!read_next("dsl_color")) {
			cerr << "parse_xml_channel: Parse error, expected </dsl_color>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_channel: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading </channel>
	if (!read_next("channel")) {
		cerr << "parse_xml_channel: Parse error, expected </channel>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param the structure that will contain type info
  *
  * Reads an entire <type> block and store information into a structure
  */
void XmlParser::parse_xml_types (PARSED_TYPE_STRUCT& _type) {
	// reading <type>
	if (!read_next("type")) {
		cerr << "parse_xml_types: Parse error, expected <type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_types: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <common_type_header>
	if (!read_next("common_type_header")) {
		cerr << "parse_xml_types: Parse error, expected <common_type_header>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// getting attributes
	sprintf(_type.name, "%s", xmlTextReaderGetAttribute(reader, (xmlChar*)"name"));
	_type.kind = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"kind_id"));
	_type.type = strtoul((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"type_id"), NULL, 0);
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_types: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	
	/*switch (_type.kind) {
		//case KIND_OF_TYPE_BUILT_IN_SIMPLE:
		case 1:
			parse_xml_simple_type(_type);
			break;
		//case KIND_OF_TYPE_DERIVED:
		//case KIND_OF_TYPE_POINTER:
		case 2:
		case 7:
			parse_xml_pointer_derived(_type);
			break;
		//case KIND_OF_TYPE_STRUCTURE:
		case 4:
			parse_xml_structure(_type);
			break;
		//case KIND_OF_TYPE_ARRAY:
		case 5:
			parse_xml_array(_type);
			break;
		//case KIND_OF_TYPE_LIST:
		case 8:
			parse_xml_list(_type);
			break;
		default:
			cerr << "parse_xml_types: Error: unknown type kind" << endl;
			abort();
	}*/
}

/**
  * @param _type the structure in which information are stored
  *
  * Parse simple type block
  */
void XmlParser::parse_xml_simple_type (PARSED_TYPE_STRUCT& _type) {
	// reading <kind_of_simple_type>
	if (!read_next("kind_of_simple_type")) {
		cerr << "parse_xml_simple_type: Parse error, expected <kind_of_simple_type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	_type.kind_of_simple_type = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"));
	// reading text value
	if (!read_next("#text")) {
		// if the text is empty, we should have read the closing tag </kind_of_simple_type>
		if (strcmp((char*)xmlTextReaderConstName(reader), "kind_of_simple_type") != 0) {
			cerr << "parse_xml_simple_type: Parse error, expected </kind_of_simple_type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	else {
		// Then, we read </kind_of_simple_type>
		if (!read_next("kind_of_simple_type")) {
			cerr << "parse_xml_simple_type: Parse error, expected </kind_of_simple_type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_simple_type: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading </type>
	if (!read_next("type")) {
		cerr << "parse_xml_simple_type: Parse error, expected </type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _type the structure in which informations are stored
  *
  * Parse derived or pointer type block
  */
void XmlParser::parse_xml_pointer_derived (PARSED_TYPE_STRUCT& _type) {
	// reading <element_type_id>
	if (!read_next("element_type_id")) {
		cerr << "parse_xml_pointer_derived: Parse error, expected <element_type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read the closing tag </element_type_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "element_type_id") != 0) {
			cerr << "parse_xml_pointer_derived: Parse error, expected </element_type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		else
			_type.elt_id = 0;
	}
	else {
		_type.elt_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </element_type_id>
		if (!read_next("element_type_id")) {
			cerr << "parse_xml_pointer_derived: Parse error, expected </element_type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_pointer_derived: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading </type>
	if (!read_next("type")) {
		cerr << "parse_xml_pointer_derived: Parse error, expected </type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _type the structure in which informations are stored
  *
  * Parse structure (and field) block
  */
void XmlParser::parse_xml_structure (PARSED_TYPE_STRUCT& _type) {
	// reading <field_count>
	if (!read_next("field_count")) {
		cerr << "parse_xml_structure: Parse error, expected <field_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty we should have read </field_count>
		if (strcmp((char*)xmlTextReaderConstName(reader), "field_count") != 0) {
			cerr << "parse_xml_structure: Parse error, expected </field_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_type.count = 0;
	}
	else {
		_type.count = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </field_count>
		if (!read_next("field_count")) {
			cerr << "parse_xml_structure: Parse error, expected </field_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// Loop for getting fields
	for (int i = 0; i < _type.count; i++) {
		PARSED_TYPE_FIELD_STRUCT _field;
		memset(&_field, 0, sizeof(_field));
		
		// reading header
		PARSED_HEADER_STRUCT _hdr;
		parse_xml_header(_hdr);
		_field.opcode = _hdr.opcode;
		// reading <type>
		if (!read_next("type")) {
			cerr << "parse_xml_structure: Parse error, expected <type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_structure: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <common_type_header> ... same, we do not need the information here
		if (!read_next("common_type_header")) {
			cerr << "parse_xml_structure: Parse error, expected <common_type_header>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_structure: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <name>
		if (!read_next("name")) {
			cerr << "parse_xml_structure: Parse error, expected <name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading text value
		if (!read_next("#text")) {
			// if the text is empty, we should have read </name>
			if (strcmp((char*)xmlTextReaderConstName(reader), "name") != 0) {
				cerr << "parse_xml_structure: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
			sprintf(_field.name, "");
		}
		else {
			char* tmp = (char*)xmlTextReaderConstValue(reader);
			memmove(_field.name, tmp, SL_MAX_IDENTIFIER_LEN);
			// reading </name>
			if (!read_next("name")) {
				cerr << "parse_xml_structure: Parse error, expected <name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_structure: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <type_id>
		if (!read_next("type_id")) {
			cerr << "parse_xml_structure: Parse error, expected <type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading text value
		if (!read_next("#text")) {
			// if text is empty, we should have read </type_id>
			if (strcmp((char*)xmlTextReaderConstName(reader), "type_id") != 0) {
				cerr << "parse_xml_structure: Parse error, expected </type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
			_field.type_id = 0;
		}
		else {
			_field.type_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
			// reading </type_id>
			if (!read_next("type_id")) {
				cerr << "parse_xml_structure: Parse error, expected </type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_structure: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <field_id>
		if (!read_next("field_id")) {
			cerr << "parse_xml_structure: Parse error, expected <field_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading text value 
		if (!read_next("#text")) {
			// if the text is empty, we should have read </field_id>
			if (!read_next("field_id")) {
				cerr << "parse_xml_structure: Parse error, expected </field_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
			_field.id = 0;
		}
		else {
			_field.id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
			// reading </field_id>
			if (!read_next("field_id")) {
				cerr << "parse_xml_structure: Parse error, expected </field_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_structure: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading </type>
		if (!read_next("type")) {
			cerr << "parse_xml_structure: Parse error, expected </type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// and we add the field to the list of fields
		_type.fields.push_back(_field);
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_structure: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading </type>
	if (!read_next("type")) {
		cerr << "parse_xml_structure: Parse error, expected </type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _type the structure in which informations are stored
  *
  * Parse array block
  */
void XmlParser::parse_xml_array (PARSED_TYPE_STRUCT& _type) {
	// reading <element_type_id>
	if (!read_next("element_type_id")) {
		cerr << "parse_xml_array: Parse error, expected <element_type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </element_type_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "element_type_id") != 0) {
			cerr << "parse_xml_array: Parse error, expected </element_type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_type.elt_id = 0;
	}
	else {
		_type.elt_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </element_type_id>
		if (!read_next("element_type_id")) {
			cerr << "parse_xml_array: Parse error, expected </element_type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_array: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <from>
	if (!read_next("from")) {
		cerr << "parse_xml_array: Parse error, expected <from>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </from>
		if (strcmp((char*)xmlTextReaderConstName(reader), "from") != 0) {
			cerr << "parse_xml_array: Parse error, expected </from>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_type.from = 0;
	}
	else {
		_type.from = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </from>
		if (!read_next("from")) {
			cerr << "parse_xml_array: Parse error, expected </from>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_array: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <till>
	if (!read_next("till")) {
		cerr << "parse_xml_array: Parse error, expected <till>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value 
	if (!read_next("#text")) {
		// if text is empty, we should have read </till>
		if (strcmp((char*)xmlTextReaderConstName(reader), "till") != 0) {
			cerr << "parse_xml_array: Parse error, expected </till>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_type.till = 0;
	}
	else {
		_type.till = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </till>
		if (!read_next("till")) {
			cerr << "parse_xml_array: Parse error, expected </till>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_array: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading </type>
	if (!read_next("type")) {
		cerr << "parse_xml_array: Parse error, expected </type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/** 
  * @param _type the structure in which informations are stored
  *
  * Parse list block
  */
void XmlParser::parse_xml_list (PARSED_TYPE_STRUCT& _type) {
	// reading <element_type_id>
	if (!read_next("element_type_id")) {
		cerr << "parse_xml_list: Parse error, expected <element_type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </element_type_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "element_type_id") != 0) {
			cerr << "parse_xml_list: Parse error, expected </element_type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_type.elt_id = 0;
	}
	else {
		_type.elt_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </element_type_id>
		if (!read_next("element_type_id")) {
			cerr << "parse_xml_list: Parse error, expected </element_type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_list: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <element_count>
	if (!read_next("element_count")) {
		cerr << "parse_xml_list: Parse error, expected <element_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </element_count>
		if (strcmp((char*)xmlTextReaderConstName(reader), "element_count") != 0) {
			cerr << "parse_xml_list: Parse error, expected </element_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_type.count = 0;
	}
	else {
		_type.count = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </element_count>
		if (!read_next("element_count")) {
			cerr << "parse_xml_list: Parse error, expected </element_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_list: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading </type>
	if (!read_next("type")) {
		cerr << "parse_xml_list: Parse error, expected </type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _var a struct that will contain variable info
  *
  * Parses a <variable> block and put information into an appropriate structure
  */
void XmlParser::parse_xml_vars (PARSED_VAR_STRUCT& _var) {
	// reading <variable>
	if (!read_next("variable")) {
		cerr << "parse_xml_vars: Parse error, expected <variable>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <name>
	if (!read_next("name")) {
		cerr << "parse_xml_vars: Parse error, expected <name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </name>
		if (strcmp((char*)xmlTextReaderConstName(reader), "name") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		sprintf(_var.name, "");
	}
	else {
		char* tmp = (char*)xmlTextReaderConstValue(reader);
		memmove(_var.name, tmp, SL_MAX_IDENTIFIER_LEN);
		// reading </name>
		if (!read_next("name")) {
			cerr << "parse_xml_vars: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <type_id>
	if (!read_next("type_id")) {
		cerr << "parse_xml_vats: Parse error, expected <type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </type_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "type_id") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_var.type_id = 0;
	}
	else {
		_var.type_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </type_id>
		if (!read_next("type_id")) {
			cerr << "parse_xml_vars: Parse error: expected </type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <variable_id>
	if (!read_next("variable_id")) {
		cerr << "parse_xml_vars: Parse error, expected <variable_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </variable_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "variable_id") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </variable_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_var.var_id = 0;
	}
	else {
		_var.var_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </variable_id>
		if (!read_next("variable_id")) {
			cerr << "parse_xml_vars: Parse error, expected </variable_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <father_variable_id>
	if (!read_next("father_variable_id")) {
		cerr << "parse_xml_vars: Parse error, expected <father_variable_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </father_variable_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "father_variable_id") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </father_variable_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_var.father_id = 0;
	}
	else {
		_var.father_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </father_variable_id>
		if (!read_next("father_variable_id")) {
			cerr << "parse_xml_vars: Parse error, expected </father_variable_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <element_from_father>
	if (!read_next("element_from_father")) {
		cerr << "parse_xml_vars: Parse error, expected <element_from_father>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </element_from_father>
		if (strcmp((char*)xmlTextReaderConstName(reader), "element_from_father") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </element_from_father>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_var.elt_from_father = 0;
	}
	else {
		_var.elt_from_father = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </element_from_father>
		if (!read_next("element_from_father")) {
			cerr << "parse_xml_vars: Parse error, expected </element_from_father>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <driver_id>
	if (!read_next("driver_id")) {
		cerr << "parse_xml_vars: Parse error, expected <driver_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </driver_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "driver_id") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </driver_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_var.driver_id = -1;
	}
	else {
		_var.driver_id = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </driver_id>
		if (!read_next("driver_id")) {
			cerr << "parse_xml_vars: Parse error, expected </driver_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <channel_id>
	if (!read_next("channel_id")) {
		cerr << "parse_xml_vars: Parse error, expected <channel_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </channel_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "channel_id") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </channel_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_var.channel_id = -1;
	}
	else {
		_var.channel_id = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </channel_id>
		if (!read_next("channel_id")) {
			cerr << "parse_xml_vars: Parse error, expected </channel_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <input_or_output>
	if (!read_next("input_or_output")) {
		cerr << "parse_xml_vars: Parse error, expected <input_or_output>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </input_or_output>
		if (strcmp((char*)xmlTextReaderConstName(reader), "input_or_output") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </input_or_output>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_var.in_or_out = -1;
	}
	else {
		_var.in_or_out = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </input_or_output>
		if (!read_next("input_or_output")) {
			cerr << "parse_xml_vars: Parse error, expected </input_or_output>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <scope_type>
	if (!read_next("scope_type")) {
		cerr << "parse_xml_vars: Parse error, expected <scope_type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </scope_type>
		if (strcmp((char*)xmlTextReaderConstName(reader), "scope_type") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </scope_type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_var.scope_type = -1;
	}
	else {
		_var.scope_type = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </scope_type>
		if (!read_next("scope_type")) {
			cerr << "parse_xml_vars: Parse error, expected </scope_type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <dsl_color>
	if (!read_next("dsl_color")) {
		cerr << "parse_xml_vars: Parse error, expected <dsl_color>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </dsl_color>
		if (!read_next("dsl_color")) {
			cerr << "parse_xml_vars: Parse error, expected </dsl_color>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_var.dsl_color = -1;
	}
	else {
		_var.dsl_color = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </dsl_color>
		if (!read_next("dsl_color")) {
			cerr << "parse_xml_vars: Parse error, expected </dsl_color>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <address>
	if (!read_next("address")) {
		cerr << "parse_xml_vars: Parse error, expected <address>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </address>
		if (strcmp((char*)xmlTextReaderConstName(reader), "address") != 0) {
			cerr << "parse_xml_vars: Parse error, expected </address>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		sprintf(_var.address, "");
	}
	else {
		sprintf(_var.address, "%s", xmlTextReaderConstValue(reader));
		// reading </address>
		if (!read_next("address")) {
			cerr << "parse_xml_vars: Parse error, expected </address>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_vars: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading </variable>
	if (!read_next("variable")) {
		cerr << "parse_xml_vars: Parse error, expected </variable>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _node a struct that will contain node info
  *
  * Parses a <node> block and put information into an appropriate structure
  */
void XmlParser::parse_xml_node (unsigned long& _node) {
	// reading <start_node>
	if (!read_next("start_node")) {
		cerr << "parse_xml_node: Parse error, expected <start_node>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	_node = strtoul((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"), NULL, 0);
}

/**
  * @param _meth a struct that will contain method information
  *
  * Reading the opening tag <method_forward>
  */
void XmlParser::parse_xml_forward_method (PARSED_METHODS_STRUCT& _meth) {
	// reading <method_forward>
	if (!read_next("method_forward")) {
		cerr << "parse_xml_forward_method: Parse error, expected <method_forward>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_methods: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	parse_xml_methods(_meth);
}

/**
  * @param _meth a struct that will contain method info
  *
  * Reading the opening tag <method>
  */
void XmlParser::parse_xml_method (PARSED_METHODS_STRUCT& _meth) {
	// reading <method>
	if (!read_next("method")) {
		cerr << "parse_xml_method: Parse error, expected <method>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_methods: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	parse_xml_methods(_meth);
}

/**
  * @param _meth a struct that will contain method information
  *
  * Parses a <method> block and put information into an appropriate structure
  */
void XmlParser::parse_xml_methods (PARSED_METHODS_STRUCT& _meth) {
	// reading <name>
	if (!read_next("name")) {
		cerr << "parse_xml_methods: Parse error, expected <name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </name>
		if (strcmp((char*)xmlTextReaderConstName(reader), "name") != 0) {
			cerr << "parse_xml_methods: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		sprintf(_meth.name, "");
	}
	else {
		char* tmp = (char*)xmlTextReaderConstValue(reader);
		memmove(_meth.name, tmp, SL_MAX_IDENTIFIER_LEN);
		// reading </name>
		if (!read_next("name")) {
			cerr << "parse_xml_methods: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_methods: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <method_id>
	if (!read_next("method_id")) {
		cerr << "parse_xml_methods: Parse error, expected <method_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </method_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "method_id") != 0) {
			cerr << "parse_xml_methods: Parse error, expected </method_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_meth.id = 0;
	}
	else {
		_meth.id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </method_id>
		if (!read_next("method_id")) {
			cerr << "parse_xml_methods: Parse error, expected </method_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_methods: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <type_id>
	if (!read_next("type_id")) {
		cerr << "parse_xml_methods: Parse error, expected <type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </type_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "type_id") != 0) {
			cerr << "parse_xml_methods: Parse error, expected </type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_meth.type_id = 0;
	}
	else {
		_meth.type_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </type_id>
		if (!read_next("type_id")) {
			cerr << "parse_xml_methods: Parse error, expected </type_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_methods: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <argument_count>
	if (!read_next("argument_count")) {
		cerr << "parse_xml_methods: Parse error, expected <argument_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </argument_count>
		if (strcmp((char*)xmlTextReaderConstName(reader), "argument_count") != 0) {
			cerr << "parse_xml_methods: Parse error, expected </argument_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_meth.argument_count = -1;
	}
	else {
		_meth.argument_count = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </argument_count>
		if (!read_next("argument_count")) {
			cerr << "parse_xml_methods: Parse error, expected </argument_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	
	/*
	// Loop to read every <variable> blocks
	while (read_next("variable")) {
		_meth.vars.push_back(parse_xml_vars());
	}
	// Finished reading <variable> blocks, we should have read <node>
	if (strcmp((char*)xmlTextReaderConstName(reader), "node") != 0) {
		cerr << "parse_xml_methods: Parse error, expected <node>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// Loop to read every instruction blocks (<node> & <instruction>)
	while (strcmp((char*)xmlTextReaderConstName(reader), "node") == 0) {
		_meth.instr_block.push_back(parse_xml_instr_block());
	}
	// finished reading <instruction> blocks, we should have read </method>
	if (strcmp((char*)xmlTextReaderConstName(reader), "method") != 0) {
		cerr << "parse_xml_methods: Parse error, expected </method>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_methods: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}*/
}

/**
  * @param _seq the struct that will contain sequence info
  *
  * Parses a <sequence> block
  */
void XmlParser::parse_xml_sequence (PARSED_SEQUENCE_STRUCT& _seq) {
	// reading <sequence>
	if (!read_next("sequence")) {
		cerr << "parse_xml_sequence: Parse error, expected <sequence>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_sequence: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <name>
	if (!read_next("name")) {
		cerr << "parse_xml_sequence: Parse error, expected <name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </name>
		if (strcmp((char*)xmlTextReaderConstName(reader), "name") != 0) {
			cerr << "parse_xml_sequence: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		sprintf(_seq.name, "");
	}
	else {
		char* tmp = (char*)xmlTextReaderConstValue(reader);
		memmove(_seq.name, tmp, SL_MAX_IDENTIFIER_LEN);
		// reading </name>
		if (!read_next("name")) {
			cerr << "parse_xml_sequence: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_sequence: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <async>
	if (!read_next("async")) {
		cerr << "parse_xml_sequence: Parse error, expected <async>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </async>
		if (strcmp((char*)xmlTextReaderConstName(reader), "async") != 0) {
			cerr << "parse_xml_sequence: Parse error, expected </async>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_seq.async = -1;
	}
	else {
		_seq.async = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </async>
		if (!read_next("async")) {
			cerr << "parse_xml_sequence: Parse error, expected </async>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_sequence: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _instr a struct that will contain instruction information
  *
  * Parses a <instruction> block an put information into an appropriate structure
  */
void XmlParser::parse_xml_instr (PARSED_INSTR_STRUCT& _instr) {
	// reading <instruction>
	if (!read_next("instruction")) {
		cerr << "parse_xml_instr: Parse error, expected <instruction>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	_instr.id = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"));
	
	/*switch (_instr.id) {
		// case DSL_INSTRUCTION_CALL:
		case 2:
			parse_xml_instr_method_call(_instr);
			break;
		// case DSL_INSTRUCTION_JUMP:
		case 4:
			parse_xml_instr_node(_instr, 1);
			break;
		// case DSL_INSTRUCTION_CJUMP:
		case 5:
			parse_xml_instr_node(_instr, 3);
			break;
		// case DSL_INSTRUCTION_PRINT:
		case 8:
			parse_xml_instr_print(_instr);
			break;
		// case DSL_INSTRUCTION_CASE_JUMP:
		case 10:
			parse_xml_instr_case_statement(_instr);
			break;
	}*/
	/*
	// After parsing nodes (DSL_INSTRUCTION_JUMP & DSL_INSTRUCTION_CJUMP), we already read <operation>
	if (_instr.id == 4 || _instr.id == 5) {
		if (strcmp((char*)xmlTextReaderConstName(reader), "operation") == 0) {
			do {
				_instr.operations.push_back(parse_xml_operation());
			} while (read_next("operation"));
		}
	}
	else {
		// Loop to read every <operation> blocks (there may be none)
		while (read_next("operation")) {
			_instr.operations.push_back(parse_xml_operation());
		}
	}
	// finished reading <operation> blocks, we should have read </instruction>
	if (strcmp((char*)xmlTextReaderConstName(reader), "instruction") != 0) {
		cerr << "parse_xml_instr: Parse error, expected </instruction>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}*/
}

/**
  * @param _op a struct that will contain operation information
  *
  * Parses a <operation> block and put information into an appropriate structure
  */
void XmlParser::parse_xml_operation (PARSED_OP_STRUCT& _op) {
	// reading <operation>
	if (!read_next("operation")) {
		cerr << "parse_xml_operation: Parse error, expected <operation>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	_op.id = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"));
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_operation: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	
	// now we determine which operation type is, to call the correct method
	switch (_op.id) {
		//case DSL_OPERATION_LOCAL_VARIABLE:
		//case DSL_OPERATION_GLOBAL_VARIABLE:
		case 1:
		case 6:
			parse_xml_op_var(_op);
			break;
		//case DSL_OPERATION_UNARY_OPERATOR:
		//case DSL_OPERATION_BINARY_OPERATOR:
		//case DSL_OPERATION_BINARY_OPERATOR_2ND_CONSTANT:
		case 2:
		case 3:
		case 4:
			parse_xml_op_operator(_op);
			break;
		//case DSL_OPERATION_LITTERAL_CONSTANT:
		case 5:
			parse_xml_op_constant(_op);
			break;
		//case DSL_OPERATION_SELECT_FROM_STACK:
		case 7:
			parse_xml_op_stack(_op);
			break;
		//case DSL_OPERATION_SELECT_FIELD:
		case 8:
			parse_xml_op_field(_op);
			break;
		//case DSL_OPERATION_SELECT_ARRAY_ELEMENT:
		case 9:
			// nothing special info to parse
			break;
		//case DSL_OPERATION_FUNCTION_CALL:
		case 10:
			parse_xml_op_function(_op);
			break;
	}
	
	// reading </operation>
	if (!read_next("operation")) {
		cerr << "parse_xml_operation: Parse error, expected </operation>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _instr the instruction struct to fill with method_call informations
  * 
  * Parses a <method_call> block and put information into the structure
  */
void XmlParser::parse_xml_instr_method_call (PARSED_INSTR_STRUCT &_instr) {
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_instr_method_call: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <method_id>
	if (!read_next("method_id")) {
		cerr << "parse_xml_instr_method_call: Parse error, expected <method_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </method_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "method_id") != 0) {
			cerr << "parse_xml_instr_method_call: Parse error, expected </method_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_instr.method_id = 0;
	}
	else {
		_instr.method_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </method_id>
		if (!read_next("method_id")) {
			cerr << "parse_xml_instr_method_call: Parse error, expected </method_call>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_instr_method_call: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <is_launch>
	if (!read_next("is_launch")) {
		cerr << "parse_xml_instr_method_call: Parse error, expected <is_launch>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </is_launch>
		if (strcmp((char*)xmlTextReaderConstName(reader), "is_launch") != 0) {
			cerr << "parse_xml_instr_method_call: Parse error, expected </is_launch>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_instr.is_launch = 0;
	}
	else {
		_instr.is_launch = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </is_launch>
		if (!read_next("is_launch")) {
			cerr << "parse_xml_instr_method_call: Parse error, expected </is_launch>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_instr_method_call: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <param_count>
	if (!read_next("param_count")) {
		cerr << "parse_xml_instr_method_call: Parse error, expected <param_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </param_count>
		if (strcmp((char*)xmlTextReaderConstName(reader), "param_count") != 0) {
			cerr << "parse_xml_instr_method_call: Parse error, expected </param_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_instr.param_count = -1;
	}
	else {
		_instr.param_count = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </param_count>
		if (!read_next("param_count")) {
			cerr << "parse_xml_instr_method_call: Parse error, expected </param_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
}

/**
  * @param _instr the instruction struct to fill with node information
  *
  * Parses <node> tags
  */
void XmlParser::parse_xml_instr_node (PARSED_INSTR_STRUCT &_instr, int nb) {
	// Loop to read nb times <node id=".." />
	for (int i = 0; i < nb; i++) {
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_instr: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <node>
		if (!read_next("node")) {
			cerr << "parse_xml_instr_jump: Parse error, expected <node>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_instr.nodes.push_back(atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id")));
	}
}

/**
  * @param _instr the instruction struct to fill with <arg_count> information
  *
  * Parses <argument_count> tag
  */
void XmlParser::parse_xml_instr_print (PARSED_INSTR_STRUCT &_instr) {
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_instr: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <argument_count>
	if (!read_next("argument_count")) {
		cerr << "parse_xml_instr: Parse error, expected <argument_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </argument_count>
		if (strcmp((char*)xmlTextReaderConstName(reader), "argument_count") != 0) {
			cerr << "parse_xml_instr: Parse error, expected </argument_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_instr.arg_count = -1;
	}
	else {
		_instr.arg_count = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </argument_count>
		if (!read_next("argument_count")) {
			cerr << "parse_xml_instr: Parse error, expected </argument_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
}

/**
  * @param _instr the instruction struct to fill with case_statement information
  *
  * Parses <case_statement> block
  */
void XmlParser::parse_xml_instr_case_statement (PARSED_INSTR_STRUCT &_instr) {
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_instr: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <elements>
	if (!read_next("elements")) {
		cerr << "parse_xml_instr: Parse error, expected <elements>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	int nb_elem = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"nb"));
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_instr: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	for (int i = 0; i < nb_elem; i++)
		_instr.cases.push_back(parse_xml_case());
	// reading </elements>
	if (!read_next("elements")) {
		cerr << "parse_xml_instr: Parse error, expected </elements>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	parse_xml_instr_node(_instr, 2);
}

/**
  * @param _plugin a string containing the plugin name
  *
  * Parses the plugin name
  */
void XmlParser::parse_xml_instr_plugin (char _plugin[SL_MAX_IDENTIFIER_LEN]) {
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_instr_plugin: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <plugin>
	if (!read_next("plugin")) {
		cerr << "parse_xml_instr_plugin: Parse error, expected <plugin>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	sprintf(_plugin, "%s", xmlTextReaderGetAttribute(reader, (xmlChar*)"name"));
}

/**
  * @return a struct with case information
  *
  * Parses a <case_statement> block and put information into an appropriate struct
  */
PARSED_CASE_STRUCT XmlParser::parse_xml_case () {
	PARSED_CASE_STRUCT _case;
	memset(&_case, 0, sizeof(_case));
	
	// reading <node>
	if (!read_next("node")) {
		cerr << "parse_xml_case: Parse error, expected <node>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	_case.node_id = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"));
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_case: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <value />
	if (!read_next("value")) {
		cerr << "parse_xml_case: Parse error, expected <value>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	_case.from = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"from"));
	_case.to   = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"to"));
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_case: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	
	return _case;
}

/**
  * @param _op the struct to store parsed informations
  *
  * Parses variable information
  */
void XmlParser::parse_xml_op_var (PARSED_OP_STRUCT& _op) {
	// reading <var_id>
	if (!read_next("var_id")) {
		cerr << "parse_xml_op_var: Parse error, expected <var_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </var_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "var_id") != 0) {
			cerr << "parse_xml_op_var: Parse error, expected </var_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_op.var_id = 0;
	}
	else {
		_op.var_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
		// reading </var_id>
		if (!read_next("var_id")) {
			cerr << "parse_xml_op_var: Parse error, expected </var_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// readin null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_op_var: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _op the struct to store parsed information
  *
  * Parses operator information
  */
void XmlParser::parse_xml_op_operator (PARSED_OP_STRUCT& _op) {
	// reading <operator>
	if (!read_next("operator")) {
		cerr << "parse_xml_op_operator: Parse error, expected <operator>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	_op.operator_id = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"));
	// reading text value -- but we do not need that information
	if (!read_next("#text")) {
		// if text is empty, we should have read </operator>
		if (strcmp((char*)xmlTextReaderConstName(reader), "operator") != 0) {
			cerr << "parse_xml_op_operator: Parse error, expected </operator>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	else {
		// reading </operator>
		if (!read_next("operator")) {
			cerr << "parse_xml_op_operator: Parse error, expected </operator>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_op_operator: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _op the struct to store parsed information
  *
  * Parses constant information
  */
void XmlParser::parse_xml_op_constant (PARSED_OP_STRUCT& _op) {
	// reading <length>
	if (!read_next("length")) {
		cerr << "parse_xml_op_constant: Parse error, expected <length>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value 
	if (!read_next("#text")) {
		// if text is empty, we should have read </length>
		if (strcmp((char*)xmlTextReaderConstName(reader), "length") != 0) {
			cerr << "parse_xml_op_constant: Parse error, expected </length>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_op.length = -1;
	}
	else {
		_op.length = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </length>
		if (!read_next("length")) {
			cerr << "parse_xml_op_constant: Parse error, expected </length>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_op_constant: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	_op.values = new char[_op.length];
	for (int i = 0; i < _op.length; i++) {
		// reading <value>
		if (!read_next("value")) {
			cerr << "parse_xml_op_constant: Parse error, expected <value>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading text value
		if (!read_next("#text")) {
			// if text is empty, we should have read </value>
			if (strcmp((char*)xmlTextReaderConstName(reader), "value") != 0) {
				cerr << "parse_xml_op_constant: Parse error, expected </value>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
		}
		else {
			_op.values[i] = atoi((char*)xmlTextReaderConstValue(reader));
			// reading </value>
			if (!read_next("value")) {
				cerr << "parse_xml_op_constant: Parse error, expected </value>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
		}
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_op_constant: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	/* PREVIOUS VERSION
	// reading <buffer>
	if (!read_next("buffer")) {
		cerr << "parse_xml_op_constant: Parse error, expected <buffer>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// Loop to read every attribute
	char attribute[20];
	for (int i = 0; i < _op.length; i++) {
		sprintf(attribute, "value_%d", i);
		_op.buf_val.push_back(atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)attribute)));
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_op_constant: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}*/
}

/**
  * @param _op the struct to store parsed information
  *
  * Parses stack information
  */
void XmlParser::parse_xml_op_stack (PARSED_OP_STRUCT& _op) {
	// reading <stack_offset>
	if (!read_next("stack_offset")) {
		cerr << "parse_xml_op_stack: Parse error, expected <stack_offset>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </stack_offset>
		if (strcmp((char*)xmlTextReaderConstName(reader), "stack_offset") != 0) {
			cerr << "parse_xml_op_stack: Parse error, expected </stack_offset>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_op.stack_offset = -1;
	}
	else {
		_op.stack_offset = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </stack_offset>
		if (!read_next("stack_offset")) {
			cerr << "parse_xml_op_stack: Parse error, expected </stack_offset>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_op_stack: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _op the struct to store parsed information
  *
  * Parses field information
  */
void XmlParser::parse_xml_op_field (PARSED_OP_STRUCT& _op) {
	// reading <field_id>
	if (!read_next("field_id")) {
		cerr << "parse_xml_op_field: Parse error, expected <field_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </field_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "field_id") != 0) {
			cerr << "parse_xml_op_field: Parse error, expected </field_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_op.field_id = -1;
	}
	else {
		_op.field_id = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </field_id>
		if (!read_next("field_id")) {
			cerr << "parse_xml_op_field: Parse error, expected </field_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_op_field: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @param _op the struct to store parsed information
  *
  * Parses function information
  */
void XmlParser::parse_xml_op_function (PARSED_OP_STRUCT& _op) {
	// reading <name>
	if (!read_next("name")) {
		cerr << "parse_xml_op_function: Parse error, expected <name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </name>
		if (strcmp((char*)xmlTextReaderConstName(reader), "name") != 0) {
			cerr << "parse_xml_op_function: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		sprintf(_op.func_name, "");
	}
	else {
		char* tmp = (char*)xmlTextReaderConstValue(reader);
		memmove(_op.func_name, tmp, SL_MAX_IDENTIFIER_LEN);
		// reading </name>
		if (!read_next("name")) {
			cerr << "parse_xml_op_function: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_op_function: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <result_type>
	if (!read_next("result_type")) {
		cerr << "parse_xml_op_function: Parse error, expected <result_type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </result_type>
		if (strcmp((char*)xmlTextReaderConstName(reader), "result_type") != 0) {
			cerr << "parse_xml_op_function: Parse error, expected </result_type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_op.func_res_type = -1;
	}
	else {
		_op.func_res_type = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </result_type>
		if (!read_next("result_type")) {
			cerr << "parse_xml_op_function: Parse error, expected </result_type>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_op_function: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <param_count>
	if (!read_next("param_count")) {
		cerr << "parse_xml_op_function: Parse error, expected <param_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </param_count>
		if (strcmp((char*)xmlTextReaderConstName(reader), "param_count") != 0) {
			cerr << "parse_xml_op_function: Parse error, expected </param_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_op.func_param_count = -1;
	}
	else {
		_op.func_param_count = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </param_count>
		if (!read_next("param_count")) {
			cerr << "parse_xml_op_function: Parse error, expected </param_count>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_op_function: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
}

/**
  * @return a struct with statements information
  *
  * Parses a <statements> block (which contains instructions blocks) and put information into an appropriate structure
  */
void XmlParser::parse_xml_stmts (PARSED_STMTS_STRUCT& _stmts) {
	// reading <statement>
	if (!read_next("statements")) {
		cerr << "parse_xml_stmts: Parse error, expected <statements>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading null value
	if (!read_next("#text")) {
		cerr << "parse_xml_stmts: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <cfg_id>
	if (!read_next("cfg_id")) {
		cerr << "parse_xml_stmts: Parse error, expected <cfg_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value 
	if (!read_next("#text")) {
		// if text is empty, we should have read </cfg_id>
		if (strcmp((char*)xmlTextReaderConstName(reader), "cfg_id") != 0) {
			cerr << "parse_xml_stmts: Parse error, expected </cfg_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		_stmts.cfg_id = -1;
	}
	else {
		_stmts.cfg_id = atoi((char*)xmlTextReaderConstValue(reader));
		// reading </cfg_id>
		if (!read_next("cfg_id")) {
			cerr << "parse_xml_stmts: Parse error, expected </cfg_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value
	if (!read_next("#text")) {
		cerr << "parse_xml_stmts: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <kind_of_cfg>
	if (!read_next("kind_of_cfg")) {
		cerr << "parse_xml_stmts: Parse error, expected <kind_of_cfg>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	_stmts.kind_of_cfg = atoi((char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"));
	// reading text value -- but we do not need that information
	if (!read_next("#text")) {
		// if text is empty, we should have read </kind_of_cfg>
		if (strcmp((char*)xmlTextReaderConstName(reader), "kind_of_cfg") != 0) {
			cerr << "parse_xml_stmts: Parse error, expected </kind_of_cfg>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	else {
		// reading </kind_of_cfg>
		if (!read_next("kind_of_cfg")) {
			cerr << "parse_xml_stmts: Parse error, expected </kind_of_cfg>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	// reading null value which corresponds to carriage return
	if (!read_next("#text")) {
		cerr << "parse_xml_stmts: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading <name>
	if (!read_next("name")) {
		cerr << "parse_xml_stmts: Parse error, expected <name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
		abort();
	}
	// reading text value
	if (!read_next("#text")) {
		// if text is empty, we should have read </name>
		if (strcmp((char*)xmlTextReaderConstName(reader), "name") != 0) {
			cerr << "parse_xml_stmts: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		sprintf(_stmts.name, "");
	}
	else {
		char* tmp = (char*)xmlTextReaderConstValue(reader);
		memmove(_stmts.name, tmp, SL_MAX_IDENTIFIER_LEN);
		// reading </name>
		if (!read_next("name")) {
			cerr << "parse_xml_stmts: Parse error, expected </name>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
	}
	
	if (_stmts.kind_of_cfg == 2 || _stmts.kind_of_cfg == 4) {
		// reading null value which corresponds to carriage return
		if (!read_next("#text")) {
			cerr << "parse_xml_stmts: Parse error, expected #text, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading <self_var_id>
		if (!read_next("self_var_id")) {
			cerr << "parse_xml_stmts: Parse error, expected <self_var_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
			abort();
		}
		// reading text value
		if (!read_next("#text")) {
			// if text is empty, we should have read </self_var_id>
			if (strcmp((char*)xmlTextReaderConstName(reader), "self_var_id") != 0) {
				cerr << "parse_xml_stmts: Parse error, expected </self_var_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
			_stmts.self_var_id = 0;
		}
		else {
			_stmts.self_var_id = strtoul((char*)xmlTextReaderConstValue(reader), NULL, 0);
			// reading </self_var_id>
			if (!read_next("self_var_id")) {
				cerr << "parse_xml_stmts: Parse error, expected </self_var_id>, got " << (char*)xmlTextReaderConstName(reader) << endl;
				abort();
			}
		}
	}
}

/*
		PRIVATE METHODS
		---------------
*/

/**
  * @param tag the expected tag to read
  *
  * @return true if the expected tag is the tag read, false otherwise
  *
  * Checks if the tag to read is the same as the one we expect
  */
bool XmlParser::read_next (char* tag) {
	if (xmlTextReaderRead(reader) == 1) {
		if (strcmp(tag, (char*)xmlTextReaderConstName(reader)) == 0)
			return true;
		else
			return false;
	}
	else 
		return false;
}
